﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Com.Stockstar.Quote.Model.Quote;
using SG.SDK.Configuration;
using SG.SDK;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

namespace Com.Stockstar.Quote.Common.Quote
{
    /// <summary>
    /// 行业成分股
    /// </summary>
    public class IndustryStockSingleton
    {
        //缓存
        private static ICacheManager cachemanager = CacheFactory.GetCacheManager();
        //缓存键值
        private static string cacheKey = "SG_IndustryStockSingleton";
        //缓存时间（单位：分钟）
        private static int cacheMinutes = 60;
        //访问实例锁
        private static Object instanceLockObject = new Object();
        ////访问数据锁
        //private static Object dataLockObject = new Object();
        //实例
        private static IndustryStockSingleton instance;
        //获取SG服务器地址
        private static string sgSDKServerAddress = ConfigurationSettings.AppSettings["SGSDKServerAddress"];
        //获取G服务器端口
        private static int sgSDKServerPort = Int32.Parse(ConfigurationSettings.AppSettings["SGSDKServerPort"]);
        //log4net日志
        protected static log4net.ILog logger = log4net.LogManager.GetLogger("Quote");
        //是否正在获取数据
        private static bool isGettingData = false;

        private IndustryStockSingleton()
        {

        }

        #region 实例
        /// <summary>
        /// 实例
        /// </summary>
        public static IndustryStockSingleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (instanceLockObject)
                    {
                        if (instance == null)
                            instance = CreateInstance();
                    }
                }

                return instance;
            }
        }
        #endregion

        #region 创建实例
        /// <summary>
        /// 创建实例
        /// </summary>
        /// <returns></returns>
        private static IndustryStockSingleton CreateInstance()
        {
            return new IndustryStockSingleton();
        }
        #endregion

        #region 缓存
        /// <summary>
        /// 缓存
        /// </summary>
        public static List<IndustryStockInfo> CacheData(List<IndustryStockInfo> oldList)
        {
            //如果没有取到数据，将保存老的数据到缓存
            List<IndustryStockInfo> dataList = GetIndustryStockList();

            if(dataList==null||dataList.Count==0)
                dataList = oldList;

            if (dataList != null && dataList.Count > 0)
            {
                cachemanager.Add(cacheKey, dataList, CacheItemPriority.Normal, new RefreshIndustryStockAction(), new AbsoluteTime(TimeSpan.FromMinutes(cacheMinutes)));
            }
            return dataList;
        }
        #endregion

        #region 获取行业成分股
        /// <summary>
        /// 获取行业成分股
        /// </summary>
        /// <returns></returns>
        private static List<IndustryStockInfo> GetIndustryStockList()
        {
            List<IndustryStockInfo> dataList = new List<IndustryStockInfo>();
            try
            {

                SDKClient client = new SDKClient(new ResourceAddress(sgSDKServerAddress, sgSDKServerPort), "INDUINDEX_STOCK");
                //获取数据

                SGObject[] array = client.GetRows();
                if (array != null && array.Length > 0)
                {
                    foreach (SGObject data in array)
                    {
                        IndustryStockInfo industryStockInfo = new IndustryStockInfo();
                        industryStockInfo.Code = data["CODE"].ToString();

                        int marketType = 1;
                        string codeValue="";

                        //成分股
                        if (data["STOCKCODES"] != null)
                        {
                            SGObject[] stockArray = data["STOCKCODES"].Children();

                            if (stockArray != null && stockArray.Length > 0)
                            {
                                industryStockInfo.StockList = new List<StockInfo>();


                                foreach (SGObject stockInfo in stockArray)
                                {
                                    StockInfo info = new StockInfo();
                                    codeValue=stockInfo["STOCKCODE"].ToString();
                                    if (!String.IsNullOrEmpty(codeValue))
                                    {
                                        if (Int32.TryParse(codeValue.Substring(0, 1), out marketType))
                                        {
                                            info.StockCode = codeValue.Substring(1, codeValue.Length - 1);
                                            info.MarketType = marketType;
                                        }
                                    }
                                    industryStockInfo.StockList.Add(info);
                                }
                            }
                        }

                        dataList.Add(industryStockInfo);
                    }
                }

                int count = dataList != null ? dataList.Count : 0;
                logger.Info(String.Format("获取行业成分股成功！数据个数{0}", count));
            }

            catch (Exception ex)
            {
                logger.Error("从SG.SDK接口获取行业成分股出错！", ex);
                return null;
            }

            return dataList;

        }
        #endregion

        #region 行业成分股
        /// <summary>
        /// 行业成分股
        /// </summary>
        public List<IndustryStockInfo> DataList
        {
            get
            {
                List<IndustryStockInfo> dataList = null;
                object data = cachemanager.GetData(cacheKey);

                if (data != null)
                {
                    dataList = (List<IndustryStockInfo>)data;
                }
                else
                {
                    //lock (dataLockObject)
                    //{
                    //    data = cachemanager.GetData(cacheKey);

                    //    if (data != null)
                    //    {
                    //        dataList = (List<IndustryStockInfo>)data;
                    //    }
                    //    else
                    //    {
                    //        dataList = CacheData(null);
                    //    }
                    //}

                    //避免死锁。
                    if (isGettingData == false)
                    {
                        isGettingData = true;
                        try
                        {
                            dataList = CacheData(null);
                        }
                        catch (Exception ex)
                        {
                            logger.Error("获取行业成功股出错。",ex);
                        }
                        isGettingData = false;
                    }

                }
                return dataList;
            }
        }
        #endregion
    }

    /// <summary>
    /// 缓存刷新
    /// </summary>
    [Serializable]
    public class RefreshIndustryStockAction : ICacheItemRefreshAction
    {
        /// <summary>
        /// 缓存刷新
        /// </summary>
        /// <param name="removedKey">移除的键</param>
        /// <param name="expiredValue">过期的值</param>
        /// <param name="removalReason">移除理由</param>
        void ICacheItemRefreshAction.Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason)
        {
            if (removalReason == CacheItemRemovedReason.Expired)
            {
                List<IndustryStockInfo> oldList = null;
                if (expiredValue != null)
                    oldList = (List<IndustryStockInfo>)expiredValue;

                IndustryStockSingleton.CacheData(oldList);
            }
        }
    }

}
